package org.kongqian.server.impl;


import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.bucket.terms.LongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.kongqian.doc.GiftDoc;
import org.kongqian.gift.util.IdName;
import org.kongqian.gift.util.PageList;
import org.kongqian.mapper.HighlightResultMapper;
import org.kongqian.query.GoodsSpuOnsaleDetailDocQuery;
import org.kongqian.repository.GiftDocRepository;
import org.kongqian.server.IGoodsSpuOnsaleDetailDocService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class GoodsSpuOnsaleDetailDocServiceImpl implements IGoodsSpuOnsaleDetailDocService {

    @Autowired
    private HighlightResultMapper highlightResultMapper;
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Autowired
    private GiftDocRepository repository;
    @Override
    public PageList<GiftDoc> search(GoodsSpuOnsaleDetailDocQuery query) {
        // 1 创建QueryBuilder对象
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();

        // 2 高级查询
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        // 2.1 关键字查询
        if(StringUtils.isNotBlank(query.getKeyword())){
            boolQuery.must(QueryBuilders.multiMatchQuery(
                    query.getKeyword(), "name","tanantName","typeName","brandName"));
        }

        // 2.2 过滤查询
        List<QueryBuilder> filter = boolQuery.filter();
        builder.withQuery(boolQuery);

        // 3 排序查询
        // 4 分页
        builder.withPageable(PageRequest.of((query.getPage()-1), query.getRows()));

        // 5 高亮查询
        HighlightBuilder.Field field1 = new HighlightBuilder.Field("name")
                .preTags("<font style='color:red'><b>").postTags("</b></font>");
        HighlightBuilder.Field field2 = new HighlightBuilder.Field("brandName")
                .preTags("<font style='color:red'><b>").postTags("</b></font>");
        HighlightBuilder.Field field3 = new HighlightBuilder.Field("typeName")
                .preTags("<font style='color:red'><b>").postTags("</b></font>");
        HighlightBuilder.Field field4 = new HighlightBuilder.Field("tenantName")
                .preTags("<font style='color:red'><b>").postTags("</b></font>");
        builder.withHighlightFields(field1,field2,field3,field4);  // 设置高亮字段

        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<span style=\"color:red;\">");    // 如果做高亮
        highlightBuilder.postTags("</span>");

        builder.withHighlightBuilder(highlightBuilder);

        //聚合 品牌
        builder.addAggregation(AggregationBuilders
                .terms("brandIdAggs").field("brandId").order(BucketOrder.count(false)).size(20)
                .subAggregation(AggregationBuilders
                        .terms("brandNameAggs").field("brandName.keyword").order(BucketOrder.count(false)).size(20))
        );
        //聚合 类型
        builder.addAggregation(AggregationBuilders
                .terms("typeIdAggs").field("typeId").order(BucketOrder.count(false)).size(20)
                .subAggregation(AggregationBuilders
                        .terms("typeNameAggs").field("typeName.keyword").order(BucketOrder.count(false)).size(20))
        );

        //聚合 租户
//        builder.addAggregation(AggregationBuilders
//                .terms("tenantIdAggs").field("tenantId").order(BucketOrder.count(false)).size(20)
//                .subAggregation(AggregationBuilders
//                        .terms("tenantNameAggs").field("tenantName.keyword").order(BucketOrder.count(false)).size(20))
//        );

        // 5 调search方法到es中查询,封装PageList对象
        AggregatedPage<GiftDoc>  aggregatedPage = elasticsearchTemplate
                .queryForPage(builder.build(), GiftDoc.class,highlightResultMapper);
        List<GiftDoc> content = aggregatedPage.getContent();    // 这是当前页数据
        long total = aggregatedPage.getTotalElements();    // 总条数
        //对聚合数据进行处理
        Map<String, List<IdName>> aggsData = handAggrs(aggregatedPage);
        PageList pageList = new PageList(total, content);
        pageList.setAggsData(aggsData);

        return pageList;   //还要返回聚合数据
    }

    private Map<String, List<IdName>> handAggrs(AggregatedPage<GiftDoc> aggregatedPage) {
        //1 获取所有的聚合
        Aggregations aggregations = aggregatedPage.getAggregations();
        Map<String, Aggregation> aggregationMap = aggregations.getAsMap();
        Set<Map.Entry<String, Aggregation>> entries = aggregationMap.entrySet();
        Iterator<Map.Entry<String, Aggregation>> iterator = entries.iterator();

        Map<String,List<IdName>> aggsData = new HashMap<>();
        while (iterator.hasNext()) { //brand  type
            //2 遍历聚合
            Map.Entry<String, Aggregation> entry = iterator.next();
            String aggsName = entry.getKey();
            Aggregation aggregation = entry.getValue();
            //id聚合
            LongTerms longTerms = (LongTerms) aggregation;
            List<LongTerms.Bucket> buckets = longTerms.getBuckets();
            List<IdName> idNames = new ArrayList<>();
            buckets.forEach(bucket -> {
                String id = bucket.getKeyAsString(); //id和
                //name聚和
                Aggregations aggregations1 = bucket.getAggregations();
                Map<String, Aggregation> asMap = aggregations1.getAsMap();
                Set<Map.Entry<String, Aggregation>> entries1 = asMap.entrySet();

                Iterator<Map.Entry<String, Aggregation>> iterator1 = entries1.iterator();
                Map.Entry<String, Aggregation> next = iterator1.next();
                StringTerms stringTerms = (StringTerms) next.getValue();
                String name = stringTerms.getBuckets().get(0).getKeyAsString();
                idNames.add(new IdName(Long.valueOf(id), name));
            });


            aggsData.put(aggsName,idNames);

        }
        return aggsData;
    }
}